﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
namespace OpencvProjectBase.TestWinform
{
    public partial class TestRect : Form
    {
        public TestRect()
        {
            InitializeComponent();
        }

        public void RectResolve()
        {
            Image<Gray, byte> image = new Image<Gray, byte>("./one1.jpg");
            Mat src=image.Mat;
            //CvInvoke.Imshow("src", src);

            //二值化
            Mat thres = new Mat();
            CvInvoke.Threshold(src, thres, 200, 255, Emgu.CV.CvEnum.ThresholdType.Binary);
            CvInvoke.Imshow("thres", thres);

            //提取目标roi

        }

        private void button1_Click(object sender, EventArgs e)
        {
            RectResolve();

            CvInvoke.WaitKey(1);
        }


        #region emgu method

        /// <summary>
        /// 获取ROI
        /// </summary>
        /// <param name="image"></param>
        /// <param name="rect"></param>
        /// <returns></returns>
        private Image<Gray, byte> GetROI(Image<Gray, byte> image, Rectangle rect)
        {
            //程序中image是原始图像，类型Image<Gray, byte>，rectangle是矩形，CropImage是截得的图像。
            Image<Gray, byte> resImag = image.CopyBlank();
            using (var mask = new Image<Gray, byte>(image.Size))
            {
                mask.SetZero();//设置所有值为0
                mask.ROI = rect;
                mask.SetValue(255);//设置ROI的值为255
                mask.ROI = Rectangle.Empty;//去掉ROI
                                           //res(I)=img1(I)+img2(I) if mask(I)!=0
                CvInvoke.BitwiseAnd(image, mask, resImag);
            }
            return resImag;
        }



        /// <summary>
        /// 合并目标轮廓
        /// </summary>
        /// <param name="vvp"></param>
        /// <param name="areaThreshold"></param>
        /// <returns></returns>
        private VectorOfPoint MergeContours(VectorOfVectorOfPoint vvp, int areaThreshold)
        {
            VectorOfPoint merged_vvp = new VectorOfPoint();
            if (vvp.Size != 0)
            {
                Console.WriteLine($"合并数量：{vvp.Size}");
                for (int vp = 0; vp < vvp.Size; vp++)
                {
                    double area = CvInvoke.ContourArea(vvp[vp]);
                    if (area > areaThreshold)//根据面积作筛选(指定最小面积,最大面积):
                    {
                        merged_vvp.Push(vvp[vp]);
                    }
                }
            }
            return merged_vvp;
        }



        public void Resolve()
        {

            gray_Img = GetROI(gray_Img, new Rectangle(300, 0, 600, 340));

            CvInvoke.MedianBlur(gray_Img, gray_Img, 11);
            //CvInvoke.Threshold(gray_Img, gray_Img, 125,255,ThresholdType.Otsu);
            CvInvoke.MorphologyEx(gray_Img, gray_Img, MorphOp.Close, kernelClosing, new Point(-1, -1), 5, BorderType.Default, new MCvScalar(255, 0, 0, 255));
            VectorOfVectorOfPoint vvp = new VectorOfVectorOfPoint();//存放的数据点
            Image<Rgb, byte> rgb_Img = BitmapExtension.ToImage<Rgb, byte>(grayBmp);                                              //VectorOfVectorOfPoint bad_vvp = new VectorOfVectorOfPoint();//存放的数据点
            VectorOfVectorOfPoint good_vvp = new VectorOfVectorOfPoint();//存放的数据点
            Mat b1 = new Mat();
            CvInvoke.FindContours(gray_Img, vvp, b1, RetrType.External, ChainApproxMethod.ChainApproxSimple);//找轮廓
            CvInvoke.DrawContours(rgb_Img, vvp, -1, new MCvScalar(0, 0, 255), 2);
            CvInvoke.Rectangle(rgb_Img, new Rectangle(300, 0, 700, 350), new MCvScalar(0, 255, 0), 3);
            bool isWorkpieces = false;
            if (vvp.Size != 0)
            {
                VectorOfPoint mergerVp = MergeContours(vvp, 100);
                if (mergerVp.Length == 0)
                {
                    Console.WriteLine("没匹配到工件");
                }
                else
                {
                    //【04】处理目标轮廓
                    var targetBox = CvInvoke.MinAreaRect(mergerVp);
                    double area = CvInvoke.ContourArea(mergerVp);
                    Console.WriteLine($"area = {area}");
                    PointF[] pt = new PointF[4];
                    pt = CvInvoke.BoxPoints(targetBox);//最小外接矩形四个角点
                    PointF po = targetBox.Center;//最小外接矩形中心
                    CvInvoke.Circle(rgb_Img, new Point((int)po.X, (int)po.Y), 8, new MCvScalar(255, 255, 0), 8);
                    Console.WriteLine($"中心：{po.X},{po.Y}");
                    if (po.X > 500 && po.X < 900)
                    {

                        for (int i = 0; i < 4; ++i)
                        {
                            Point p1 = new Point((int)pt[i].X, (int)pt[i].Y);
                            Point p2 = new Point((int)pt[(i + 1) % 4].X, (int)pt[(i + 1) % 4].Y);
                            CvInvoke.Line(rgb_Img, p1, p2, new MCvScalar(0, 0, 255), 2);
                        }
                        VectorOfPoint points = new VectorOfPoint();
                        CvInvoke.ConvexHull(mergerVp, points);
                        Console.WriteLine("凸包个数：" + points.Length.ToString());
                        //PointF[] pf = rect.GetVertices();
                        for (int i = 0; i < 4; i++)
                        {
                            CvInvoke.Circle(rgb_Img, new Point((int)pt[i].X, (int)pt[i].Y), 8, new MCvScalar(255, 0, 0), 4);
                        }
                        if (area > 12000)
                        {
                            Console.WriteLine($"frameCnt = {frameCnt} :{area} 检测出五星脚");
                            label1.Invoke(new Action(() =>
                            {
                                label1.Text = $"frameCnt = {frameCnt} :检测出五星脚";
                            }));
                            isWorkpieces = true;
                            if (frameCnt != 0)
                            {

                                if (cycleCnt == 0 && frameCnt == 1)
                                {
                                    Console.WriteLine("第一帧 发送。。。" + $"{0},{2},{frameCnt}");
                                    tcpServerEx.SentMsg(robotip, $"{0},{2},{frameCnt}");
                                }
                                else
                                {
                                    queueCode.Enqueue($"{0},{2},{frameCnt}");
                                }

                            }

                        }
                        else if (area > 3000 && area <= 12000)
                        {

                            isWorkpieces = true;
                            Console.WriteLine($"frameCnt = {frameCnt} :{area} 检测出十字角");
                            label1.Invoke(new Action(() =>
                            {
                                label1.Text = $"frameCnt = {frameCnt} :检测出十字角";
                            }));
                            if (frameCnt != 0)
                            {
                                if (cycleCnt == 0 && frameCnt == 1)
                                {
                                    Console.WriteLine("第一帧 发送。。。" + $"{0},{3},{frameCnt}");
                                    tcpServerEx.SentMsg(robotip, $"{0},{3},{frameCnt}");
                                }
                                else
                                {
                                    queueCode.Enqueue($"{0},{3},{frameCnt}");
                                }


                            }

                        }
                    }

                }
            }
            else
            {
                Console.WriteLine($" i = {0} area = {0}");
            }
            if (!isWorkpieces)
            {
                Console.WriteLine($"frameCnt = {frameCnt} : nothing");
                label1.Invoke(new Action(() =>
                {
                    label1.Text = $"frameCnt = {frameCnt} :空挂钩";
                }));
                if (frameCnt != 0)
                {
                    if (cycleCnt == 0 && frameCnt == 1)
                    {
                        Console.WriteLine("第一帧 发送。。。" + $"{0},{0},{frameCnt}");
                        tcpServerEx.SentMsg(robotip, $"{0},{0},{frameCnt}");
                    }
                    else
                    {
                        queueCode.Enqueue($"{0},{0},{frameCnt}");
                    }


                }
            }
        }


      
        #endregion
    }
}
